import java.io.*;
import java.util.*;

public class WF {
    //输出某个英文文本文件中 26 字母出现的频率，由高到低排列，并显示字母出现的百分比，精确到小数点后面两位。
    //命令行参数是：wf.exe -c <file name>
    public void step0(String filepath) {
        String string = null;
        //定义两个数组用来存字母和其对应的数字
        int a[] = new int[52];
        char b[] = new char[52];
        b[0] = 'a';
        b[1] = 'b';
        b[2] = 'c';
        b[3] = 'd';
        b[4] = 'e';
        b[5] = 'f';
        b[6] = 'g';
        b[7] = 'h';
        b[8] = 'i';
        b[9] = 'j';
        b[10] = 'k';
        b[11] = 'l';
        b[12] = 'm';
        b[13] = 'n';
        b[14] = 'o';
        b[15] = 'p';
        b[16] = 'q';
        b[17] = 'r';
        b[18] = 's';
        b[19] = 't';
        b[20] = 'u';
        b[21] = 'v';
        b[22] = 'w';
        b[23] = 'x';
        b[24] = 'y';
        b[25] = 'z';
        b[26] = 'A';
        b[27] = 'B';
        b[28] = 'C';
        b[29] = 'D';
        b[30] = 'E';
        b[31] = 'F';
        b[32] = 'G';
        b[33] = 'H';
        b[34] = 'I';
        b[35] = 'J';
        b[36] = 'K';
        b[37] = 'L';
        b[38] = 'M';
        b[39] = 'N';
        b[40] = 'O';
        b[41] = 'P';
        b[42] = 'Q';
        b[43] = 'R';
        b[44] = 'S';
        b[45] = 'T';
        b[46] = 'U';
        b[47] = 'V';
        b[48] = 'W';
        b[49] = 'X';
        b[50] = 'Y';
        b[51] = 'Z';


        try {
            // 在给定从中读取数据的文件名的情况下创建一个新 FileReader
            FileReader fr = new FileReader(filepath);

            // 创建一个使用默认大小输入缓冲区的缓冲字符输入流
            BufferedReader br = new BufferedReader(fr);

            while (null != (string = br.readLine())) {
                int sum = string.length();
                //对字符串循环判断，存在五十二个字母里的让其数量加一，不存在舍去
                for (int i = 0; i < sum; i++) {
                    switch (string.charAt(i)) {
                        case 'a':
                            a[0]++;
                            break;
                        case 'b':
                            a[1]++;
                            break;
                        case 'c':
                            a[2]++;
                            break;
                        case 'd':
                            a[3]++;
                            break;
                        case 'e':
                            a[4]++;
                            break;
                        case 'f':
                            a[5]++;
                            break;
                        case 'g':
                            a[6]++;
                            break;
                        case 'h':
                            a[7]++;
                            break;
                        case 'i':
                            a[8]++;
                            break;
                        case 'j':
                            a[9]++;
                            break;
                        case 'k':
                            a[10]++;
                            break;
                        case 'l':
                            a[11]++;
                            break;
                        case 'm':
                            a[12]++;
                            break;
                        case 'n':
                            a[13]++;
                            break;
                        case 'o':
                            a[14]++;
                            break;
                        case 'p':
                            a[15]++;
                            break;
                        case 'q':
                            a[16]++;
                            break;
                        case 'r':
                            a[17]++;
                            break;
                        case 's':
                            a[18]++;
                            break;
                        case 't':
                            a[19]++;
                            break;
                        case 'u':
                            a[20]++;
                            break;
                        case 'v':
                            a[21]++;
                            break;
                        case 'w':
                            a[22]++;
                            break;
                        case 'x':
                            a[23]++;
                            break;
                        case 'y':
                            a[24]++;
                            break;
                        case 'z':
                            a[25]++;
                            break;
                        case 'A':
                            a[26]++;
                            break;
                        case 'B':
                            a[27]++;
                            break;
                        case 'C':
                            a[28]++;
                            break;
                        case 'D':
                            a[29]++;
                            break;
                        case 'E':
                            a[30]++;
                            break;
                        case 'F':
                            a[31]++;
                            break;
                        case 'G':
                            a[32]++;
                            break;
                        case 'H':
                            a[33]++;
                            break;
                        case 'I':
                            a[34]++;
                            break;
                        case 'J':
                            a[35]++;
                            break;
                        case 'K':
                            a[36]++;
                            break;
                        case 'L':
                            a[37]++;
                            break;
                        case 'M':
                            a[38]++;
                            break;
                        case 'N':
                            a[39]++;
                            break;
                        case 'O':
                            a[40]++;
                            break;
                        case 'P':
                            a[41]++;
                            break;
                        case 'Q':
                            a[42]++;
                            break;
                        case 'R':
                            a[43]++;
                            break;
                        case 'S':
                            a[44]++;
                            break;
                        case 'T':
                            a[45]++;
                            break;
                        case 'U':
                            a[46]++;
                            break;
                        case 'V':
                            a[47]++;
                            break;
                        case 'W':
                            a[48]++;
                            break;
                        case 'X':
                            a[49]++;
                            break;
                        case 'Y':
                            a[50]++;
                            break;
                        case 'Z':
                            a[51]++;
                    }
                }
            }
            fr.close();
            br.close();
        } catch (Exception ee) {
            ee.printStackTrace();
        }
        //统计总次数
        int max = 0;
        double s = 0;
        for (int i = 0; i < 52; i++) {
            s += a[i];
        }
        System.out.println("总次数" + s);
        for (int j = 0; j < 52; j++) {
            int c = 0;
            for (int i = 0; i < 52; i++) {
                //排序
                if (a[i] > max) {
                    max = a[i];
                    c = i;
                }
                //按照顺序输出字母及其占比，保留两位小数
                if (i == 51) {
                    System.out.print(b[c] + "  次数   " + a[c] + "   出现率   ");
                    System.out.println(String.format("%.2f", a[c] / s * 100) + "%");
                    a[c] = 0;
                    c = 0;
                    max = 0;
                }
            }
        }
    }

    public void step1(String path,int num){
        File file = new File(path);
        try {
            FileReader fr = new FileReader(file);
            BufferedReader bufr = new BufferedReader(fr);
            String s = "";
            Map<String, Integer> tm = new TreeMap<String, Integer>();
            String[] strs;
            //把文件读进来一行一行进行处理，按照正则表达式匹配除字母数字以外的符号进行分割
            while ((s = bufr.readLine()) != null) {
                strs= s.toLowerCase().split("[^a-z0-9]+");
                for (int i = 0; i < strs.length; i++) {
                    //如果字符串为空或者字符串第一个为数字的话舍去
                    if(strs[i].equals("") || strs[i].toCharArray()[0]<='9'){
                        continue;
                    }
                    //判断字符串是否已经存入treemap，如果不，则存入且数量为1，反之使其数量加一再存入
                    if (!tm.containsKey(strs[i])) {
                        tm.put(strs[i], 1);
                    } else {
                        tm.put(strs[i], tm.get(strs[i]) + 1);
                    }
                }
            }

            //对Treemap进行按照value进行降序排序，value值相等时按照字典对key进行排序
            List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(tm.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
                public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                    if (o1.getValue() == o2.getValue()) {
                        return o1.getKey().compareTo(o2.getKey());
                    }
                    return o2.getValue().compareTo(o1.getValue());
                }
            });

            //count可以控制输出的数量
            int count=0;
            for (Map.Entry<String, Integer> entry : list) {
                count++;
                System.out.println(entry.getKey()+":"+entry.getValue());
                if(count==num)
                    break;
            }


//            for(int p =0;p< strs.length-1;p++){
//                for (int q =0;q< strs.length-1-p;q++){
//                    if(r2[q]<r2[q+1]){
//                        int temp=r2[q];
//                        r2[q]=r2[q+1];
//                        r2[q+1]=temp;
//                        String tems=r1[q];
//                        r1[q]=r1[q+1];
//                        r1[q+1]=tems;
//                    }
//                }
//            }

            System.out.println("完成");

            bufr.close();
            fr.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //循环遍历文件夹下的每一个txt文件及文件夹内的txt文件
    public void getPath(String a){
        File file = new File(a);
        File []array =file.listFiles();
        for(int i=0;i<array.length;i++) {
            //判断是否是目录
            if(array[i].isDirectory()) {
                getPath(array[i].getPath());
                }else {
                step1(array[i].getPath(),0);
                }
            }
    }
    //循环遍历文件夹下的每一个txt文件
    public void getPath_c(String a){
        File file = new File(a);
        File []array =file.listFiles();
        for(int i=0;i<array.length;i++) {
            //判断是否是目录
            if(array[i].isDirectory()) {
                continue;
            }else {
                step1(array[i].getPath(),0);
            }
        }
    }

    public void step2(String filepath,String stopwordpath){
//        File file1 = new File("D:\\WorkSpace\\work\\软件工程\\one.txt");
//        File file2 = new File("D:\\WorkSpace\\work\\软件工程\\stopwords_en.txt");

    File file1 = new File(filepath);
    File file2 = new File(stopwordpath);

    try {
        FileReader fr1 = new FileReader(file1);
        FileReader fr2 = new FileReader(file2);

        BufferedReader bur1 = new BufferedReader(fr1);
        BufferedReader bur2 = new BufferedReader(fr2);

        Map<String, Integer> imap = new TreeMap<String, Integer>();
        Map<String, Integer> nmap = new TreeMap<String, Integer>();

        //对于两个txt文件分别进行存储进treemap
        String line = "";
        String[] strs;
        while ((line=bur1.readLine()) != null) {
            strs= line.toLowerCase().split("[^a-z0-9]+");
            for (int i = 0; i < strs.length; i++) {
                if(strs[i].equals("") || strs[i].toCharArray()[0]<='9'){
                    continue;
                }
                if (!imap.containsKey(strs[i])) {
                    imap.put(strs[i], 1);
                } else {
                    imap.put(strs[i], imap.get(strs[i]) + 1);
                }
            }
        }

        line = "";
        String[] strs1;
        while ((line = bur2.readLine()) != null) {
            strs1= line.toLowerCase().split("[^a-z0-9]+");
            for (int i = 0; i < strs1.length; i++) {
                if(strs1[i].equals("") || strs1[i].toCharArray()[0]<='9'){
                    continue;
                }
                if (!nmap.containsKey(strs1[i])) {
                    nmap.put(strs1[i],1);
                } else {
                    continue;
                }
            }
        }

        //排序
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(imap.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                if (o1.getValue() == o2.getValue()) {
                    return o1.getKey().compareTo(o2.getKey());
                }
                return o2.getValue().compareTo(o1.getValue());
            }
        });

        //在停词表里出现过的不存入
        for (Map.Entry<String, Integer> entry : list) {
                if(nmap.containsKey(entry.getKey())){}
                else{
                    System.out.println(entry.getKey()+":"+entry.getValue());
                }
        }

        fr1.close();
        fr2.close();
        bur1.close();
        bur2.close();

    } catch (Exception e) {
        e.printStackTrace();
    }

}

    public void step3(Integer n) {

        try {
//            String fileName = "D:\\WorkSpace\\work\\软件工程\\one.txt"; // 文件名字
            FileReader fr = new FileReader("D:\\WorkSpace\\work\\软件工程\\one.txt");
            BufferedReader bufr = new BufferedReader(fr);
            Map<String, Integer> count = new TreeMap<String, Integer>();
            String s = "";
            String text = "";

            while ((s = bufr.readLine()) != null) {
                text = s.toLowerCase();

                //替换掉除空格外的所有标点符号，并且按照空格分隔文章
                text = text.replaceAll("[^0-9a-zA-Z\\s+]+", " ### ");
                String words[] = text.split("\\s+");//分割一个或多个空格

                //按规定数量找到短语
                for (int i = 0; i < words.length; i++) {
                    String sentence = "";
                    int j;
                    for(j = i; j < n + i && j < words.length; j++) {
                        if(words[j].equals("")) break;
                        sentence += words[j] + " ";
                    }
                    if(sentence.contains("###")||sentence.equals("")||j!=n+i) {}//包含###的字符串不符合要求，去除
                    else {
                        int cnt = 1;
                        if (count.get(sentence) != null) cnt = count.get(sentence) + 1;
                        count.put(sentence, cnt);
                    }
                }
            }



            //对treemap进行排序
            List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(count.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
                @Override
                public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                    if (o1.getValue().compareTo(o2.getValue()) == 0) {
                        return o1.getKey().compareTo(o2.getKey());
                    }
                    return o2.getValue().compareTo(o1.getValue());
                }
            });

            int c=0;
            for(Map.Entry<String,Integer> entry : list){//输出短语及其数量,c也可控制输出数量
                if(c==10)
                    break;
                else{
                    c++;
                    System.out.println(entry.getKey()+":"+entry.getValue());
                }
            }

            fr.close();
            bufr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void step4(String v){
        File file1 = new File(v);
        File file2 = new File("D:\\WorkSpace\\work\\软件工程\\one.txt");

        try {
            FileReader fr1 = new FileReader(file1);
            FileReader fr2 = new FileReader(file2);

            BufferedReader bur1 = new BufferedReader(fr1);
            BufferedReader bur2 = new BufferedReader(fr2);

            Map<String, Integer> imap = new TreeMap<String, Integer>();
            Map<String, Integer> nmap = new TreeMap<String, Integer>();

            //对动词表按行存入
            String line = "";
            while ((line=bur1.readLine()) != null) {
                line= "#"+line.toLowerCase().replaceAll("[^a-z0-9]+","#")+"#";
                nmap.put(line,1);
            }


            List<Map.Entry<String, Integer>> list1 = new ArrayList<Map.Entry<String, Integer>>(nmap.entrySet());
            line = "";
            String[] strs1;
            while ((line = bur2.readLine()) != null) {
                strs1= line.toLowerCase().split("[^a-z0-9]+");
                for (int i = 0; i < strs1.length; i++) {
                    if(strs1[i].equals("") || strs1[i].toCharArray()[0]<='9'){
                        continue;
                    }

                    String aaa ="";
                    for(Map.Entry<String,Integer> nentry:list1){
                        //判断是否包含了此单词，包含则进行分割并存入第一个单词，即动词原形
                        String a = nentry.getKey().toString();
                        if(a.contains("#"+strs1[i]+"#")){
                            String[] aa = a.split("[^a-z0-9]+");
                            aaa = aa[1];
                            break;
                        }

                    }

                    //存入
                    if(!aaa.equals("")){
                        if (!imap.containsKey(aaa)) {
                            imap.put(aaa,1);
                        } else {
                            imap.put(aaa,imap.get(aaa)+1);
                        }
                    }else{
                        if (!imap.containsKey(strs1[i])) {
                            imap.put(strs1[i],1);
                        } else {
                            imap.put(strs1[i],imap.get(strs1[i])+1);
                        }
                    }

                }
            }

            //排序
            List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(imap.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
                public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                    if (o1.getValue() == o2.getValue()) {
                        return o1.getKey().compareTo(o2.getKey());
                    }
                    return o2.getValue().compareTo(o1.getValue());
                }
            });

            //输出
            for (Map.Entry<String, Integer> entry : list) {
                System.out.println(entry.getKey()+":"+entry.getValue());
            }

            fr1.close();
            fr2.close();
            bur1.close();
            bur2.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        WF wf = new WF();
        String option = args[0];
        if(option.equals("-c")){
            //字母频率 = 这个字母出现的次数 / （所有A-Z，a-z字母出现的总数）
            //如果两个字母出现的频率一样，那么就按照字典序排列。
            wf.step0(args[1]);
        }
        else if(option.equals("-f")){
            //输出文件中所有不重复的单词，按照出现次数由多到少排列，出现次数同样多的，以字典序排列。
            wf.step1(args[1],0);
        }
        else if(option.equals("-n")){
            //支持 -n 参数，输出出现次数最多的前 n 个单词， 例如， -n 10 就是输出最常出现单词的前 10 名。
            // 当没有指明数量的时候，我们默认列出所有单词的频率。
            if(args.length==2)
                wf.step1("D:\\WorkSpace\\work\\软件工程\\one.txt",Integer.parseInt(args[1]));
            else
                wf.step1("D:\\WorkSpace\\work\\软件工程\\one.txt",0);
        }
        else if(option.equals("-d")&&!(args[1].equals("-s"))){
            //wf.exe -d 指定文件目录，对目录下每一个文件执行 wf.exe -f 的操作。
            wf.getPath(args[1]);
        }
        else if(option.equals("-d")&&args[1].equals("-s")){
            //wf.exe -d -s 同上， 但是会递归遍历目录下的所有子目录。
            wf.getPath_c(args[2]);
        }
        else if(option.equals("-x")){
            // 我们可以做一个 stop word 文件 （停词表）， 在统计词汇的时候，跳过这些词。 我们把这个文件叫 “stopwords.txt” file.
            wf.step2(args[1],args[3]);
        }
        else if(option.equals("-p")){
            //找短语支持新的命令行参数 -p 参数 说明要输出多少个词的短语，并按照出现频率排列。同一频率的词组， 按照字典序来排列。
            wf.step3(Integer.parseInt(args[1]));
        }
        else if(option.equals("-v")){
            //把动词的各种变形都归为它的原型来统计。
            wf.step4(args[1]);
        }
    }
}
